package com.ruoyi.project.erp.service.impl;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.YearMonth;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.PageUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.security.LoginUser;
import com.ruoyi.framework.web.page.TableDataInfo;
import com.ruoyi.project.erp.domain.*;
import com.ruoyi.project.erp.dto.SubmitWorkLogDTO;
import com.ruoyi.project.erp.dto.WorklogQuery;
import com.ruoyi.project.erp.mapper.*;
import com.ruoyi.project.erp.query.WorklogStatisticsQuery;
import com.ruoyi.project.erp.service.ITaskService;
import com.ruoyi.project.erp.vo.*;
import com.ruoyi.project.system.domain.SysDept;
import com.ruoyi.project.system.domain.SysUser;
import com.ruoyi.project.system.mapper.SysDeptMapper;
import com.ruoyi.project.system.mapper.SysRoleMapper;
import com.ruoyi.project.system.mapper.SysUserMapper;
import com.ruoyi.project.system.mapper.SysUserRoleMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.project.erp.service.IWorklogService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

/**
 * 工时Service业务层处理
 * 
 * @author ruoyi
 * @date 2025-06-19
 */
@Service
public class WorklogServiceImpl implements IWorklogService 
{

    private static final BigDecimal TOTAL_HOURS_IN_DAY = new BigDecimal("24");
    @Autowired
    private WorklogMapper worklogMapper;
    @Autowired
    private TaskMemberMapper taskMemberMapper;
    @Autowired
    private TaskMapper taskMapper;

    @Autowired
    private SysDeptMapper deptMapper;

    @Autowired
    private SysUserMapper userMapper;
    @Autowired
    private WorklogApprovalMapper worklogApprovalMapper;
    /**
     * 查询工时
     * 
     * @param id 工时主键
     * @return 工时
     */
    @Override
    public Worklog selectWorklogById(Long id)
    {
        return worklogMapper.selectWorklogById(id);
    }

    /**
     * 查询工时列表
     * 
     * @param worklog 工时
     * @return 工时
     */
    @Override
    public List<Worklog> selectWorklogList(Worklog worklog)
    {
        return worklogMapper.selectWorklogList(worklog);
    }

    /**
     * 新增工时
     * 
     * @param worklog 工时
     * @return 结果
     */
    @Override
    public int insertWorklog(Worklog worklog)
    {
        worklog.setCreateTime(DateUtils.getNowDate());
        return worklogMapper.insertWorklog(worklog);
    }


    /**
     * 提交工时
     * 1. 移除了自动计算加班的逻辑
     * 2. 每日工时上限已调整为24小时
     * @param submitWorkLogDTO 前端提交的工时数据
     * @return 结果
     */
    @Override
    @Transactional
    public int submitWorklog(Worklog submitWorkLogDTO) {
        // 0. 数据准备
        LoginUser user = SecurityUtils.getLoginUser();
        SysUser sysUser = user.getUser();
        Worklog worklog = new Worklog();
        BeanUtils.copyProperties(submitWorkLogDTO, worklog);
        worklog.setUserId(sysUser.getDdUserId());
        worklog.setCreateTime(DateUtils.getNowDate());

        // 1. 获取用户提交的总工时和加班工时
        BigDecimal totalHours = worklog.getHours();
        BigDecimal overtimeHours = worklog.getOvertimeHours() == null ? BigDecimal.ZERO : worklog.getOvertimeHours();

        // 2. 核心逻辑：校验并设置加班工时
        if (totalHours == null || totalHours.compareTo(BigDecimal.ZERO) <= 0) {
            throw new ServiceException("必须填写有效的总工时！");
        }
        if (overtimeHours.compareTo(BigDecimal.ZERO) < 0) {
            throw new ServiceException("加班工时不能为负数！");
        }
        if (overtimeHours.compareTo(totalHours) > 0) {
            throw new ServiceException("加班工时不能大于总工时！");
        }

        worklog.setOvertimeHours(overtimeHours);
        worklog.setIsOvertime(overtimeHours.compareTo(BigDecimal.ZERO) > 0 ? 1 : 0);

        // 3. 校验任务成员和每日工时上限
        Task task = taskMapper.selectTaskById(submitWorkLogDTO.getTaskId());
        if (task == null) {
            throw new ServiceException("关联的任务不存在！");
        }

        List<TaskMember> taskMembers = taskMemberMapper.selectTaskMemberByTaskId(task.getId());
        List<String> userIds = taskMembers.stream().map(TaskMember::getUserId).collect(Collectors.toList());
        if (!userIds.contains(sysUser.getDdUserId())) {
            throw new RuntimeException("您不是该任务的成员，无法提交工时~");
        }

        // --- 这里的校验逻辑会使用上面修改后的 TOTAL_HOURS_IN_DAY 常量 ---
        LocalDate workDate = submitWorkLogDTO.getWorkDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        BigDecimal loggedHours = worklogMapper.selectMyLeftWorkHours(workDate, sysUser.getDdUserId());
        if (loggedHours == null) {
            loggedHours = BigDecimal.ZERO;
        }
        BigDecimal remainingHours = TOTAL_HOURS_IN_DAY.subtract(loggedHours);
        if (remainingHours.compareTo(totalHours) < 0) {
            throw new RuntimeException("提交失败，您在该工作日剩余可填报工时为 " + remainingHours + " 小时");
        }

        // 4. 设置其他属性并插入数据库
        worklog.setProjectId(task.getProjectId());
        worklog.setFinalStatus("pending");
        worklog.setClosedLoop(submitWorkLogDTO.getClosedLoop());
        worklog.setWorkStyle(submitWorkLogDTO.getWorkStyle());
        worklogMapper.insertWorklog(worklog);

        // 5. 创建审批流记录
        WorklogApproval worklogApproval = new WorklogApproval();
        worklogApproval.setWorklogId(worklog.getId());
        worklogApproval.setStep(1L);

        Long deptId = user.getDeptId();
        if (deptId == null) {
            throw new RuntimeException("无法找到您的部门信息，无法创建审批流~");
        }
        SysDept dept = deptMapper.selectDeptById(deptId);
        if (dept == null || StringUtils.isEmpty(dept.getLeader())) {
            throw new RuntimeException("您所在的部门未设置负责人，无法创建审批流~");
        }
        worklogApproval.setApproverId(dept.getLeader());
        worklogApproval.setStatus("pending");
        worklogApproval.setCreateTime(DateUtils.getNowDate());
        return worklogApprovalMapper.insertWorklogApproval(worklogApproval);
    }
//    @Override
//    public int submitWorklog(Worklog submitWorkLogDTO) {
//        // 获取当前用户ID
//        Worklog worklog = new Worklog();
//        BeanUtils.copyProperties(submitWorkLogDTO,worklog);
//        LoginUser user = SecurityUtils.getLoginUser();
//        SysUser sysUser = user.getUser();
//        worklog.setUserId(user.getUser().getDdUserId());
//        // 如果工时超过8小时，设置为加班
//        if (worklog.getHours().compareTo(new BigDecimal("8")) == 1) {
//            worklog.setIsOvertime(1); // 1表示加班
//            worklog.setOvertimeHours(worklog.getHours().subtract(new BigDecimal("8"))); // 计算加班工时
////        } else if (worklog.getHours().compareTo(new BigDecimal("16")) == 1) {
////            throw new ServiceException("每日工时，不可超过 16 工时 !"); // 非加班时加班工时为0
//        } else {
//            worklog.setIsOvertime(0); // 0表示非加班
//            worklog.setOvertimeHours(BigDecimal.ZERO); // 非加班时加班工时为0
//        }
//        worklog.setCreateTime(DateUtils.getNowDate());
//        Task task = taskMapper.selectTaskById(submitWorkLogDTO.getTaskId());
//
//        List<TaskMember> taskMembers = taskMemberMapper.selectTaskMemberByTaskId(task.getId());
//        List<String> userIds = taskMembers.stream().map(TaskMember::getUserId).collect(Collectors.toList());
//        if (!userIds.contains(sysUser.getDdUserId())){
//            throw new RuntimeException("您不是任务成员~");
//        }
////        List<Worklog> worklog1 = worklogMapper.selectWorkLogByUserIdAndTaskId(sysUser.getDdUserId(),task.getId());
////        List<Date> workDates = worklog1.stream().map(Worklog::getWorkDate).collect(Collectors.toList());
//        LocalDate localDate = LocalDate.now();
//        BigDecimal loggedHours = worklogMapper.selectMyLeftWorkHours(localDate,sysUser.getDdUserId());
//        BigDecimal leftHours = TOTAL_HOURS_IN_DAY.subtract(loggedHours);
//        if (leftHours.compareTo(submitWorkLogDTO.getHours()) < 0){
//            throw new RuntimeException("已超过该日提交工时上限~");
//        }
//        worklog.setProjectId(task.getProjectId());
//        worklog.setFinalStatus("pending");
//        WorklogApproval worklogApproval1 = new WorklogApproval();
////        Worklog worklog1 = worklogMapper.selectMyWorkLogByUserIdAndWorkDate(sysUser.getDdUserId(),submitWorkLogDTO.getWorkDate(),submitWorkLogDTO.getTaskId());
////        if (!ObjectUtils.isEmpty(worklog1)){
////            BeanUtils.copyProperties(worklog,worklog1);
////            worklogMapper.updateWorklog(worklog1);
////            worklogApproval1 = worklogApprovalMapper.selectByWorklogId(worklog1.getId());
////        }else{
//        worklogMapper.insertWorklog(worklog);
////        }
//        WorklogApproval worklogApproval = new WorklogApproval();
//        worklogApproval.setWorklogId(worklog.getId());
//        worklogApproval.setStep(1L);
//// 1. 获取提交人所属部门ID
//        Long deptId = user.getDeptId();
//        if(deptId == null) {
//            throw new RuntimeException("该用户无部门~");
//        }
//
//
//
//
//
//
//
//
//
//        SysDept dept = deptMapper.selectDeptById(deptId);
//        worklogApproval.setApproverId(dept.getLeader());
//        worklogApproval.setStatus("pending");
//        worklogApproval.setCreateTime(DateUtils.getNowDate());
////        if (!ObjectUtils.isEmpty(worklogApproval1)){
////            BeanUtils.copyProperties(worklogApproval,worklogApproval1);
////            return worklogApprovalMapper.updateWorklogApproval(worklogApproval1);
////        }else {
//            return worklogApprovalMapper.insertWorklogApproval(worklogApproval);
////        }
//
//    }

    @Override
    public List<MyWorkLogInfoVo> getMyWorkLog(String userId) {
        return worklogMapper.selectMyWorkLogByUserId(userId);
    }

    @Override
    public void submitWorkLog(SubmitWorkLogDTO submitWorkLogDTO) {
        Worklog worklog = new Worklog();
        BeanUtils.copyProperties(submitWorkLogDTO,worklog);

    }

    @Override
    public List<UserWorklogInfoVO> getUserWorklogInfo(String taskId) {
        List<Worklog> worklogList = worklogMapper.selectWorklogByTaskId(taskId);
        List<UserWorklogInfoVO> collect = worklogList.stream().map(w -> {
            UserWorklogInfoVO userWorklogInfoVO = new UserWorklogInfoVO();
            BeanUtils.copyProperties(w, userWorklogInfoVO);
            SysUser user = userMapper.selectUserByDdUserId(w.getUserId());
            userWorklogInfoVO.setUserName(user.getNickName());
            return userWorklogInfoVO;
        }).collect(Collectors.toList());
        return collect;
    }

    @Override
    public List<WorklogVO> selectList(WorklogQuery query) {
        return worklogMapper.selectList(query);
    }

    @Override
    public List<WorklogCalendarVO> getWorklogCalendarData(String month) {
        // 1. 获取当前登录用户ID
        LoginUser loginUser = SecurityUtils.getLoginUser();
        SysUser user = loginUser.getUser();
        String userId = user.getDdUserId();
        // 2. 解析月份，并获取该月的天数和起止日期
        YearMonth yearMonth;
        try {
            yearMonth = YearMonth.parse(month);
        } catch (Exception e) {
            throw new ServiceException("月份格式不正确，请使用 'yyyy-MM' 格式");
        }
        Date beginDate = Date.from(yearMonth.atDay(1).atStartOfDay(ZoneId.systemDefault()).toInstant());
        Date endDate = Date.from(yearMonth.atEndOfMonth().atTime(23, 59, 59).atZone(ZoneId.systemDefault()).toInstant());

        // 3. 从数据库查询当月已填写的工时记录
        List<WorklogCalendarVO> loggedDays = worklogMapper.selectDailyWorklogHours(userId, beginDate, endDate);

        // 4. 将查询结果转换为 Map<日期, 工时>，方便快速查找
        // Key: "2023-11-01", Value: 8.0
        Map<String, BigDecimal> loggedHoursMap = loggedDays.stream()
                .collect(Collectors.toMap(WorklogCalendarVO::getWorkDate, WorklogCalendarVO::getTotalHours));

        // 5. 生成当月完整的日历列表
        List<WorklogCalendarVO> fullCalendar = new ArrayList<>();
        int daysInMonth = yearMonth.lengthOfMonth(); // 获取当月总天数

        // 6. 遍历当月的每一天
        for (int day = 1; day <= daysInMonth; day++) {
            // 使用 LocalDate 更方便地处理日期
            LocalDate currentDate = yearMonth.atDay(day);
            String currentDateStr = currentDate.toString(); // 格式默认为 "yyyy-MM-dd"

            WorklogCalendarVO dailyVo = new WorklogCalendarVO();
            dailyVo.setWorkDate(currentDateStr);

            // 从Map中获取工时，如果Map中没有这一天，则使用默认值 BigDecimal.ZERO
            BigDecimal hours = loggedHoursMap.getOrDefault(currentDateStr, BigDecimal.ZERO);
            dailyVo.setTotalHours(hours);

            fullCalendar.add(dailyVo);
        }

        // 7. 返回完整的日历数据
        return fullCalendar;
    }

    @Override
    public List<WorklogVO> selectExportList(WorklogQuery query) {
        return worklogMapper.selectExportList(query);
    }

    @Override
    public List<WorklogStatisticsVO> selectDeptWorklogStatistics(WorklogStatisticsQuery query) {
        if ("\"\"".equals(query.getUserId()) || "".equals(query.getUserId())) {
            query.setUserId(null);
        }

        System.out.println("清理后的userId: [" + query.getUserId() + "]");
        List<WorklogStatisticsVO> list = worklogMapper.selectWorklogStatistics(query);
        return list;
    }

    @Override
    public List<WorklogStatisticsVO> selectPersonalWorklogStatistics(WorklogStatisticsQuery query) {
        List<WorklogStatisticsVO> list = worklogMapper.selectPersonalWorklogStatistics(query);
        return list;
    }

    @Override
    public WorklogStatisticsSummaryVO selectDeptWorklogStatisticsSummary(WorklogStatisticsQuery query) {
        if ("\"\"".equals(query.getUserId()) || "".equals(query.getUserId())) {
            query.setUserId(null);
        }
        WorklogStatisticsSummaryVO summary = new WorklogStatisticsSummaryVO();

        // 总工时统计
        BigDecimal totalHours = worklogMapper.selectTotalHours(query);
        summary.setTotalHours(totalHours != null ? totalHours : BigDecimal.ZERO);

        // 加班统计
        OvertimeStatisticsVO overtimeStats = worklogMapper.selectOvertimeStatistics(query);
        summary.setOvertimeStatistics(overtimeStats);

        // 服务范围统计
        ServiceScopeStatisticsVO serviceScopeStats = worklogMapper.selectServiceScopeStatistics(query);
        summary.setServiceScopeStatistics(serviceScopeStats);

        // 服务方式统计
        ServiceMethodStatisticsVO serviceMethodStats = worklogMapper.selectServiceMethodStatistics(query);
        summary.setServiceMethodStatistics(serviceMethodStats);

        // 服务阶段统计
        List<ServiceStageStatisticsVO> serviceStageStats = worklogMapper.selectServiceStageStatistics(query);
        summary.setServiceStageStatistics(serviceStageStats);

        return summary;
    }

    @Override
    public WorklogStatisticsSummaryVO selectPersonalWorklogStatisticsSummary(WorklogStatisticsQuery query) {
        WorklogStatisticsSummaryVO summary = new WorklogStatisticsSummaryVO();

        // 总工时统计
        BigDecimal totalHours = worklogMapper.selectPersonalTotalHours(query);
        summary.setTotalHours(totalHours != null ? totalHours : BigDecimal.ZERO);

        // 加班统计
        OvertimeStatisticsVO overtimeStats = worklogMapper.selectPersonalOvertimeStatistics(query);
        summary.setOvertimeStatistics(overtimeStats);

        // 服务范围统计
        ServiceScopeStatisticsVO serviceScopeStats = worklogMapper.selectPersonalServiceScopeStatistics(query);
        summary.setServiceScopeStatistics(serviceScopeStats);

        // 服务方式统计
        ServiceMethodStatisticsVO serviceMethodStats = worklogMapper.selectPersonalServiceMethodStatistics(query);
        summary.setServiceMethodStatistics(serviceMethodStats);

        // 服务阶段统计
        List<ServiceStageStatisticsVO> serviceStageStats = worklogMapper.selectPersonalServiceStageStatistics(query);
        summary.setServiceStageStatistics(serviceStageStats);

        return summary;
    }

    /**
     * 修改工时
     * 
     * @param worklog 工时
     * @return 结果
     */
    @Override
    public int updateWorklog(Worklog worklog)
    {
        worklog.setUpdateTime(DateUtils.getNowDate());
        return worklogMapper.updateWorklog(worklog);
    }

    /**
     * 批量删除工时
     * 
     * @param ids 需要删除的工时主键
     * @return 结果
     */
    @Override
    public int deleteWorklogByIds(Long[] ids)
    {
        return worklogMapper.deleteWorklogByIds(ids);
    }

    /**
     * 删除工时信息
     * 
     * @param id 工时主键
     * @return 结果
     */
    @Override
    public int deleteWorklogById(Long id)
    {
        return worklogMapper.deleteWorklogById(id);
    }
}
